/*
 * proc.h
 *
 *  Created on: 2016-10-3
 *      Author: m
 */

#ifndef SRC_PROC_PROC_H_
#define SRC_PROC_PROC_H_

#include "protect.h"
#include "type.h"
#include "fs.h"
#include "ipc_type.h"

#define LDT_ITEM_COUNT  (2)
#define PROC_FD_MAX     (16)

#define TASK_IDX_TTY        (0)
#define TASK_IDX_SYS        (1)
#define TASK_IDX_HD_DRV     (2)
#define TASK_IDX_FS         (3)
#define TASK_IDX_USER_A     (4)
#define TASK_IDX_USER_B     (5)
#define TASK_IDX_USER_C     (6)
#define TASK_IDX_LAST       TASK_IDX_USER_C

#define NR_TASKS        (TASK_IDX_LAST + 1)

#define INTERRUPT           (0xFFF7)
#define TASK_ANY            (0xFFFA)
#define TASK_NONE           (0xFFFE)

#define STACK_SIZE      (0x8000)

#define NR_SYSCALL        (2)

#define PROC_ST_READY       (0)
#define PROC_ST_SENDING     (1)
#define PROC_ST_RECEIVING   (2)
#define PROC_ST_ERR         (4)

//function
#define FN_BOTH     (0)
#define FN_SEND     (1)
#define FN_RECV     (2)

//msg type
#define MT_GET_TICKS    (1)
#define MT_DEV_OPEN     (2)
#define MT_INTERRUPT    (3)
#define MT_FDISK_LIST   (4)
#define MT_HD_READ      (5)
#define MT_HD_WRITE     (6)
#define MT_HD_IO_CTRL   (7)
#define MT_FS_OPEN      (8)
#define MT_FS_CLOSE     (9)
#define MT_SYSCAL_RET   (0xEF)

struct _PROCESS;

typedef struct {
    u32 gs; //[0] +0
    u32 fs; //[1] +4
    u32 es; //[2] +8
    u32 ds; //[3] +12
    u32 edi; //[4] +16
    u32 esi; //[5] +20
    u32 ebp; //[6] +24
    u32 kernel_esp; //[7] +28
    u32 ebx; //[8] +32
    u32 edx; //[9] +36
    u32 ecx; //[10] +40
    u32 eax; //[11] +44
    u32 retaddr; //[12] +48 0x30
    u32 eip; //[13] +52 0x34
    u32 cs; //[14] +56 0x38
    u32 eflags; //[15] +60 0x3C
    u32 esp; //[16] +64 0x40
    u32 ss; //[17] +68 0x44
} __attribute((packed)) STACK_FRAME;

typedef struct _MESSAGE {
    int req_pid;
    int type;
    char data[32];
} MESSAGE;
typedef struct __PROC_COMMUNICATION {
    MESSAGE* msg;
    int recv_from;
    int send_to;
    int has_int_msg;
    struct _PROCESS* q_sending;
    struct _PROCESS* next_sending;
} __attribute((packed)) PROC_COM;

typedef struct _PROCESS {
    STACK_FRAME     regs;
    unsigned short  ldt_sel; // +72 0x48
    DESCRIPTOR      ldts[LDT_ITEM_COUNT];
    u32             pid;
    char            name[32]; //process name
    u32             tty_no;
    u32             state;
    int             ticks;//remain ticks
    int             priority;
    PROC_COM        ipc;
    FILE_DESC*      fd_arr[PROC_FD_MAX];
} __attribute__((packed)) PROCESS;


typedef struct s_task {
    task_f  initial_eip;
    u32     stack_top;
    u32     stack_size;
    int     priority;
    char    name[32];
} TASK;


void test_b();
void test_c();
void test_a();

int init_proc(PROCESS* p, TASK* t);
void shedule();

int post(int func, int dest_pid, MESSAGE* msg);
int post_impl(int func, int dest_pid, MESSAGE* msg, PROCESS* req);
void notify_int(int pid);

#endif /* SRC_PROC_PROC_H_ */
